﻿using Mapster;
using Microsoft.EntityFrameworkCore;
using WorldmeServer.Attributes;
using WorldmeServer.DTO.用户相关;
using WorldmeServer.Models.Base;
using WorldmeServer.Models.用户相关;
using WorldmeServer.Services.Database;
using WorldmeServer.Utils;

namespace WorldmeServer.Services.Business.用户相关
{
    [ScopedRegistration]
    public class AuthService
    {
        private readonly MySqlContext mysql;
        private readonly RedisService redis;

        public AuthService(MySqlContext mysql, RedisService redis)
        {
            this.mysql = mysql;
            this.redis = redis;
        }

        public async Task<ServiceResult<UserVo>> Login(LoginUserDto dto)
        {
            // 验证参数合法性
            if (!ValidationUtils.IsValidEmail(dto.Email, out string errorMsg))
            {
                return ServiceResult<UserVo>.Fail(errorMsg);
            }
            // 检查邮箱是否注册
            var user = await mysql.Users.FirstOrDefaultAsync(u => u.Email == dto.Email);
            if (user == null)
            {
                return ServiceResult<UserVo>.Fail("邮箱未注册，请先注册");
            }
            // 检查邮箱和密码
            bool success = EncryptUtils.ComputeSha256Hash(user.Salt + dto.Password + user.Salt) == user.Password;
            if (!success)
            {
                return ServiceResult<UserVo>.Fail("密码错误，请重新输入");
            }

            string token = JwtUtils.GenerateToken(user);

            UserVo vo = user.Adapt<UserVo>();

            vo.AccessToken = token;

            return ServiceResult<UserVo>.Success(vo);
        }

        public async Task<ServiceResult<UserVo>> Register(RegisterUserDTO dto)
        {
            // 验证参数合法性
            if (!ValidationUtils.IsValidEmail(dto.Email, out string errorMsg))
            {
                return ServiceResult<UserVo>.Fail(errorMsg);
            }
            if (!ValidationUtils.IsValidPassword(dto.Password, out errorMsg))
            {
                return ServiceResult<UserVo>.Fail(errorMsg);
            }

            if (await mysql.Users.AnyAsync(u => u.Email == dto.Email))
            {
                return ServiceResult<UserVo>.Fail("邮箱已被注册，请检查是否正确");
            }
            if (!redis.DefaultDb.KeyExists(dto.Email))
            {
                return ServiceResult<UserVo>.Fail("邮箱验证码已失效，请重新获取验证码");
            }
            string code = redis.DefaultDb.StringGet(dto.Email);
            if (dto.Code != code)
            {
                return ServiceResult<UserVo>.Fail("邮箱验证码错误");
            }
            // 验证成功后删除redis记录
            redis.DefaultDb.KeyDelete(dto.Email);
            // 生成所需数据
            string uid = RandomUtils.GenerateUid();
            string salt = RandomUtils.GenerateSalt();

            // 哈希密码
            string hashPassword = EncryptUtils.ComputeSha256Hash(salt + dto.Password + salt);

            // 生成用户数据 并添加到数据库
            User user = new User
            {
                Id = uid,
                UserName = dto.Email!,
                Salt = salt,
                Email = dto.Email!,
                Password = hashPassword,
            };

            // 注册成功直接登录返回token
            string token = JwtUtils.GenerateToken(user);
            // 生成对应头像
            File.Copy(Constant.PATH_AVATAR_DEFAULT, Path.Combine(Constant.PATH_AVATAR,uid));

            await mysql.Users.AddAsync(user);
            await mysql.SaveChangesAsync();


            UserVo vo = user.Adapt<UserVo>();
            vo.AccessToken = token;

            return ServiceResult<UserVo>.Success(vo);
        }

        public async Task<ServiceResult<Boolean>> SendVerificationEmail(SendEmailDto dto)
        {
            // 验证参数合法性
            if (!ValidationUtils.IsValidEmail(dto.Email, out string errorMsg))
            {
                return ServiceResult<Boolean>.Fail(errorMsg);
            }
            Dictionary<string, object> param = new Dictionary<string, object>();
            param["username"] = dto.Email;

            // 从数据库获取该邮箱的用户名
            var user = mysql.Users.FirstOrDefault(u => u.Email == dto.Email);
            if (user != null)
            {
                param["username"] = user.UserName;
            }

            // 生成验证码
            string code = RandomUtils.GenerateCode();
            param["code"] = code;

            // 发送验证码邮件
            EmailUtils.SendEmail(dto.Email, "default", param);

            // 将验证码存储到redis中用于后续验证
            redis.DefaultDb.StringSet(dto.Email, code, TimeSpan.FromMinutes(3));
            return ServiceResult<Boolean>.Success(true);
        }
    }
}
